﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using MediaRecommender.Controller;

namespace MediaRecommender.Model
{
    //Collection class to hold users consumed media
    [Serializable()]
    public class MediaList : IDictionary<Media, int>, ISerializable
    {
        #region Fields
        private Dictionary<Media, int> _mediaList;
        private User _user;
        private List<double> _vectorRepresentation;
        private List<double> _associatedPeopleVector;
        #endregion

        #region Constructors
        public MediaList(User user)
        {
            this._mediaList = new Dictionary<Media, int>();
            this.VectorRepresentation = new List<double>();
            this.AssociatedPeopleVector = new List<double>();
            this.User = user;

            if (MediaCollection.Instance.CountPeople() != 0)
                for (int i = 0; i < MediaCollection.Instance.ReturnAssociatedPeopleVector().Count; i++)
                    this.AssociatedPeopleVector.Add(0);

            for (int i = 0; i < Enum.GetNames(typeof(Genre)).Length; i++)
                VectorRepresentation.Add(0);
        }
        #endregion Constructors

        #region Properties
        public User User
        {
            get { return this._user; }
            private set { this._user = value; }
        }

        public List<double> VectorRepresentation
        {
            get { return this._vectorRepresentation; }
            protected set { this._vectorRepresentation = value; }
        }

        public List<double> AssociatedPeopleVector
        {
            get { return this._associatedPeopleVector; }
            protected set { this._associatedPeopleVector = value; }
        }

        public ICollection<Media> Keys
        {
            get { return _mediaList.Keys; }
        }

        public ICollection<int> Values
        {
            get { return _mediaList.Values; }
        }

        public Dictionary<Media, int> UserMediaList
        {
            get { return _mediaList; }
            private set { _mediaList = value; }
        }

        public int this[Media key]
        {
            get { return _mediaList[key]; }
            set { _mediaList[key] = value; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }
        #endregion

        #region Serialization
        public MediaList(SerializationInfo info, StreamingContext ctxt)
        {
            this.UserMediaList = (Dictionary<Media, int>)info.GetValue("UserMediaList", typeof(Dictionary<Media, int>));
            this.User = (User)info.GetValue("User", typeof(User));
            this.VectorRepresentation = (List<double>)info.GetValue("VectorRepresentation", typeof(List<double>));
            this.AssociatedPeopleVector = (List<double>)info.GetValue("AssociatedPeopleVector", typeof(List<double>));
        }

        public virtual void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("UserMediaList", this.UserMediaList);
            info.AddValue("User", this.User);
            info.AddValue("VectorRepresentation", this.VectorRepresentation);
            info.AddValue("AssociatedPeopleVector", this.AssociatedPeopleVector);
        }
        #endregion

        #region Methods
        public void Add(Media key, int value)
        {
            this._mediaList.Add(key, value);
        }

        public void Add(KeyValuePair<Media, int> item)
        {
            this.Add(item.Key, item.Value);
        }

        public bool Remove(Media key)
        {
            MedialistController mlc = new MedialistController(this.User);
            return mlc.RemoveMedia(key);
        }

        public bool Remove(KeyValuePair<Media, int> item)
        {
            return this.Remove(item.Key);
        }

        public bool ContainsKey(Media key)
        {
            if (_mediaList.ContainsKey(key))
                return true;
            return false;
        }

        public bool TryGetValue(Media key, out int value)
        {
            return _mediaList.TryGetValue(key, out value);
        }

        public void Clear()
        {
            this._mediaList.Clear();
        }

        public bool Contains(KeyValuePair<Media, int> item)
        {
            return this._mediaList.Contains(item);
        }

        public void CopyTo(KeyValuePair<Media, int>[] array, int arrayIndex)
        {
            this._mediaList.ToList().CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return this._mediaList.Count(); }
        }
        #endregion

        #region Enumerators
        public IEnumerator<KeyValuePair<Media, int>> GetEnumerator()
        {
            return _mediaList.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _mediaList.GetEnumerator();
        }
        #endregion
    }
}